package Jona;

/**
 * @author Xox Ix
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class Power extends Statement {
	ArgObject weakSet, strongSet;
	
	/**
	 * Creates a new power relation "weak < strong"
	 * @param weak weakest of the two sets
	 * @param strong strongest of the two sets
	 */
	public Power(ArgObject strong, ArgObject weak) {	
		super(ArgObject.ASSUMPTION, "");
		setWeak(weak);
		setStrong(strong);		
	}
	
	/**
	 * Creates a new power relation "weak < strong" with the
	 * given supporter and attacker relations
	 * @param weak weakest of the two sets
	 * @param strong strongest of the two sets
	 * @param supporters Array of the relation's supporters
	 * @param attackers Array of the relation's attackers
	 */
	public Power(ArgObject strong, ArgObject weak, ArgObject[] supporters, ArgObject[] attackers) {	
		super(ArgObject.ASSUMPTION, "", supporters, attackers);
		setWeak(weak);
		setStrong(strong);
	}
	
	public void setWeak(ArgObject newWeak) {
		weakSet = newWeak;
	}

	public void setStrong(ArgObject newStrong) {
		strongSet = newStrong;
	}
	
	public ArgObject[] getStrong() {
		if (strongSet == null) {
			return new ArgObject[0];
		} else if (strongSet instanceof Conjunct) {
			return ((Conjunct)strongSet).getOperands();
		}
		ArgObject [] tmp = new ArgObject[1];
		tmp[0] = strongSet;
		return tmp;
	}

	public ArgObject[] getWeak() {
		if (weakSet == null) {
			return new ArgObject[0];
		} else if (weakSet instanceof Conjunct) {
			return ((Conjunct)weakSet).getOperands();
		}
		ArgObject [] tmp = new ArgObject[1];
		tmp[0] = weakSet;
		return tmp;
	}

	/**
	 * Tests whether all Statements in the strong set are
	 * undefeated in the given Theory 
	 * @param th Theory to test
	 * @return
	 * true is this relation is applicable,
	 * false otherwise
	 */
	public boolean applicable(Theory th) {
		int i;
		ArgObject [] statements = getStrong();
		for (i = 0; i < statements.length; ++i) {
			if (th.getValue(statements[i]) != ArgObject.EVALUATION_UNDEFEATED) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * If applicable, it defeats all statements in the weak set
	 * @param th Theory in which to change the values
	 * @return 
	 * true if the application of this Power changed the Theory's evaluation,
	 * false otherwise
	 */
	public boolean apply(Theory th) {
		int i;
		boolean retVal;
		ArgObject [] statements = getWeak();
		retVal = false;
		if (applicable(th)) {
			for (i = 0; i < statements.length; ++i) {
				if (th.getValue(statements[i]) != ArgObject.EVALUATION_DEFEATED && th.getValue(statements[i]) != ArgObject.EVALUATION_UNASSIGNED) {
					th.setValue(statements[i],ArgObject.EVALUATION_DEFEATED);
					retVal = true;
				}
			}
		}
		if (retVal) {
			System.out.println("Statement '"+weakSet.getText()+"' overpowered by '"+strongSet.getText()+"'");
		}
		return retVal;
	}
	
	/**
	 * Determines whether other cannot be applied if this is undefeated
	 * @param other other Power set
	 * @return
	 * true if other cannot be applied if this is applied,
	 * false otherwise
	 */
	public boolean invalidates(Power other) {
		ArgObject [] set1, set2;
		int i,j;
		
		set1 = getWeak();
		set2 = other.getStrong();
		for (i = 0; i < set1.length; ++i) {
			for (j = i; j < set2.length; ++j) {
				if (set1[i] == set2[j]) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Determines whether all other's strong statements
	 * are in this one's weak set and not all this one's
	 * strong statements are in other's weak set.
	 * @param other other Power set
	 * @return
	 * true if all other's strong statements are in this 
	 * one's weak set and not all this one's strong 
	 * statements are in other's weak set,
	 * false otherwise
	 */
	public boolean overrules(Power other) {
		ArgObject [] set1, set2;
		int i,j;
		boolean found;
		
		set1 = getWeak();
		set2 = other.getStrong();
		for (i = 0; i < set2.length; ++i) {
			found = false;
			j = 0;
			while (j < set1.length && !found) {
				if (set1[i] == set2[j]) {
					found = true;
				}
				j++;
			}
			if (!found) {
				return false;
			}
		}
		// All other's strong are in this one's weak
		set1 = getStrong();
		set2 = other.getWeak();
		for (i = 0; i < set1.length; ++i) {
			found = false;
			j = 0;
			while (j < set2.length && !found) {
				if (set1[i] == set2[j]) {
					found = true;
				}
				j++;
			}
			if (!found) {
				return true;
				// One of this one's strong is not in other's weak
			}
		}
		return false;
		// Other's strong is in this one's weak and vice versa
	}

	public String getText(){
		String rt;
		rt = "(";
		if (strongSet != null) {
			rt += strongSet.getText();
		}
		rt += ") > (";
		if (weakSet != null) {
			rt += weakSet.getText();
		}
		return rt+")";
	}
	
	public boolean isUndefeated(Theory th) {
		int i, valAtt, valCond;
		ArgObject [] attackers = getAttackers();
		for (i = 0; i < attackers.length; ++i) {
			valAtt = th.getValue(attackers[i]); 
			valCond = th.getValue(th.getConditional(attackers[i],getNegation()));
			if (valAtt != ArgObject.EVALUATION_UNASSIGNED && valAtt != ArgObject.EVALUATION_DEFEATED &&
					(valCond != ArgObject.EVALUATION_UNASSIGNED || attackers[i] instanceof Power) && valCond != ArgObject.EVALUATION_DEFEATED) {
				return false;
			}
		}
		return true;
	}

	public int evaluate(Theory th) {
		int i;
		ArgObject [] statements = getStrong();
		for (i = 0; i < statements.length; ++i) {
			if (th.getValue(statements[i]) == ArgObject.EVALUATION_DEFEATED) {
				return ArgObject.EVALUATION_DEFEATED;
			}
		}
		return super.evaluate(th);
		
	}

}
